﻿/******************************************************************************
 * This file is part of libemb.
 *
 * libemb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libemb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libemb.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project: Embedme
 * Author : FergusZeng
 * Email  : cblock@126.com
 * git	  : https://git.oschina.net/cblock/embedme
 * Copyright 2014~2017 @ ShenZhen ,China
*******************************************************************************/
#ifndef __SOCKET_H__
#define __SOCKET_H__

#include "BaseType.h"
#include "IODevice.h"
#include "Mutex.h"
#include "Thread.h"

#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <iostream>
#include <vector>

/** 定义socket的属性 */
typedef enum
{
    SOCKET_ATTR_CASTTYPE,
    SOCKET_ATTR_RCVBUF,
    SOCKET_ATTR_SNDBUF,
    SOCKET_ATTR_ADDR,
    SOCKET_ATTR_PORT,
    SOCKET_ATTR_UNKNOWN=0xFF,
}SOCKET_ATTR_E;

/** 定义socket的可选项 */
typedef enum
{
    SOCKET_BROADCAST,  /**< 广播 */
    SOCKET_GROUPCAST,  /**< 组播 */
    SOCKET_MULTICAST,  /**< 多播 */
}SOCKET_CASTTYPE_E;

/** 定义socket的类型 */
typedef enum
{
    SOCKET_TYPE_UDP,  /**< UDP */
    SOCKET_TYPE_TCP,  /**< TCP */
}SOCKET_TYPE_E;

/** 定义tcp连接状态 */
typedef enum
{
    TCP_LINK_DISCONNECT,    /**< 断开状态 */
    TCP_LINK_CONNECTED,     /**< 连接状态 */
}TCP_LINK_E;


/**
 *  \file   Socket.h   
 *  \class  Socket
 *  \brief  Socket抽象基类	
 */

class Socket:public IODevice{
public:
    Socket();
    virtual ~Socket();
    virtual bool open(const char *device, int ioMode=IO_MODE_INVALID);
    virtual bool close();
    virtual int peekData(char *buf, int len, int timeoutMs=-1);
    virtual int readData(char *buf, int len, int timeoutMs=-1);
    virtual int writeData(const char *buf, int len,int timeoutMs=-1);
    virtual int setAttribute(int attr, int value);
    virtual int getAttribute(int attr);
    bool isAlive();
    virtual bool open();
    virtual bool bind(uint16 localPort=0,std::string localAddr=""); 
    virtual bool connectToHost(uint16 peerPort,std::string peerAddr); 
protected:
    int m_sockfd;
    struct sockaddr_in m_localSockAddr;
    std::string m_peerAddr;
    uint16 m_peerPort;
};

/**
 *  \file   Socket.h   
 *  \class  UdpSocket
 *  \brief  UdpSocket类	
 */

class UdpSocket:public Socket{
public:
    UdpSocket();
    virtual ~UdpSocket();
    bool open();
    bool close();
    int readData(char* buf,int len,int timeoutMs=-1);
    int writeData(const char* buf,int len, int timeoutMs=-1);    
};

/**
 *  \file   Socket.h   
 *  \class  TcpSocket
 *  \brief  TcpSocket类	
 */

class TcpSocket:public Socket{
public:
    TcpSocket();
    virtual ~TcpSocket();
    bool open();
    bool close();
    bool listenConnection(int maxpend);                        /* 监听连接 */
    bool acceptConnection(TcpSocket& newSocket);               /* 接受连接 */
    bool connectToHost(uint16 peerPort,std::string peerAddr);  /* 连接对端 */
};

/**
 *  \file   Socket.h   
 *  \class  LocalTcpSocket
 *  \brief  LocalTcpSocket类	
 */

class LocalTcpSocket:public Socket{
public:
    LocalTcpSocket();
    virtual ~LocalTcpSocket();
    bool open();
    bool close();
    bool bindLocal(std::string localName);            /* 绑定本地连接 */
    bool connectLocal(std::string localName);         /* 连接本地连接 */
    bool listenConnection(int maxpend);               /* 监听连接 */
    bool acceptConnection(LocalTcpSocket& newSocket); /* 接受连接 */
private:
    struct sockaddr_un m_sockaddr;
};

/**
 *  \file   Socket.h   
 *  \class  TcpServer
 *  \brief  TcpServer类	
 */
class TcpServer:public Runnable{
public:
    TcpServer();
    virtual ~TcpServer();
    bool initServer(uint16 serverPort,std::string serverIP="127.0.0.1",int maxPendings=1);
    virtual bool startServer();
    virtual bool stopServer();
    virtual void onNewConnection(Socket* connSocket)=0;
private:
    void run();
protected:
    std::vector<Socket*> m_clientCollection;
private:
    TcpSocket m_serverSocket;
    Thread m_mainThread;
};

/**
 *  \file   Socket.h   
 *  \class  LocalTcpServer
 *  \brief  LocalTcpServer	
 */
class LocalTcpServer:public TcpServer{
public:
    LocalTcpServer();
    virtual ~LocalTcpServer();
    bool initServer(std::string serverName,int maxPendings=1);
private:
    void run();
private:
    LocalTcpSocket m_serverSocket;
};

#endif
